import { Dialog } from '@taroify/core'
import { BaseEventOrig } from '@tarojs/components'

import { catchify } from '@/utils/hackify'
import { useBindPhone } from './useBindPhone'
import { useUserStore } from './useUserStore'
import { createEventHook } from './createEventHook'

export type AuthType = 'getPhoneNumber' | 'getRealtimePhoneNumber'

export type UseAuthHandlerOptions = {
  openType?: AuthType
}

const getPhoneNumber = <V = Data>(
  onAuth: (e: BaseEventOrig<{ errMsg?: string; code?: string }>) => Promise<V>,
  options: {
    openType?: AuthType
    onGetPhoneNumber?: (e: BaseEventOrig<{ errMsg?: string; code?: string }>) => void
    onGetRealTimePhoneNumber?: (e: BaseEventOrig<{ errMsg?: string; code?: string }>) => void
  } = {}
) => {
  const { openType = 'getPhoneNumber' } = options

  return new Promise((resolve, reject) => {
    const onGetPhoneNumber = (e: BaseEventOrig<{ errMsg?: string; code?: string }>) => {
      options.onGetPhoneNumber?.(e)
      onAuth(e).then(resolve).catch(reject)
    }
    const onGetRealTimePhoneNumber = (e: BaseEventOrig<{ errMsg?: string; code?: string }>) => {
      options.onGetRealTimePhoneNumber?.(e)
      onAuth(e).then(resolve).catch(reject)
    }

    Dialog.confirm({
      title: '未登录',
      message: '请先登录',
      confirm: {
        openType: openType,
        children: '授权登录',
        onGetPhoneNumber,
        onGetRealTimePhoneNumber,
      },
    })
  })
}

export function useAuthHandler<R = any, P extends unknown[] = unknown[]>(
  service: Service<R, P>,
  options: UseAuthHandlerOptions = {}
) {
  const { isAuthed } = useUserStore()
  const [loading, bindPhone] = useBindPhone()

  const onGetPhoneNumberHook = createEventHook<BaseEventOrig<{ errMsg: string; code?: string }>>()
  const onGetRealtimePhoneNumberHook = createEventHook<BaseEventOrig<{ errMsg: string; code?: string }>>()

  const handler = async (...args: P) => {
    if (!isAuthed) {
      const [e] = await catchify(getPhoneNumber)(bindPhone, {
        openType: options.openType,
        onGetPhoneNumber: onGetPhoneNumberHook.trigger,
        onGetRealTimePhoneNumber: onGetRealtimePhoneNumberHook.trigger,
      })

      if (e) {
        console.error('[useAuthHandler] getPhoneNumber error', e)
        throw e
      }
    }

    return service(...args)
  }

  return {
    loading,
    execute: handler,
    onGetPhoneNumber: onGetPhoneNumberHook.on,
    onGetRealtimePhoneNumber: onGetRealtimePhoneNumberHook.on,
  }
}
